package com.zmn.plat.business.impl.service.item;

import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.plat.business.interfaces.channel.ChannelServiceCategoryBService;
import com.zmn.plat.business.interfaces.product.tariff.item.ProductServiceItemPriceBService;
import com.zmn.plat.business.interfaces.service.item.ServiceItemBService;
import com.zmn.plat.business.interfaces.service.item.servicetime.ServServiceTimeBService;
import com.zmn.plat.business.interfaces.service.tariff.channel.ChannelTariffBService;
import com.zmn.plat.common.constant.ProductConsts;
import com.zmn.plat.common.dictionary.PlatErrorCodeDict;
import com.zmn.plat.common.dictionary.WarrantyRuleEnum;
import com.zmn.plat.common.dto.product.MaxAveragePriceDRO;
import com.zmn.plat.common.dto.service.item.*;
import com.zmn.plat.common.exception.PlatException;
import com.zmn.plat.manager.dictionary.ProductDict;
import com.zmn.plat.model.dto.service.ItemPriceCalDTO;
import com.zmn.plat.model.entity.category.BaseCategory;
import com.zmn.plat.model.entity.category.BaseCategoryQuery;
import com.zmn.plat.model.entity.product.ServProduct;
import com.zmn.plat.model.entity.product.tariff.item.ProductTariffGroupItemQuery;
import com.zmn.plat.model.entity.servcategory.ServAssCategoryQuery;
import com.zmn.plat.model.entity.servcategory.ServCategory;
import com.zmn.plat.model.entity.servcategory.ServTariffAssCategoryQuery;
import com.zmn.plat.model.entity.service.category.ItemCategory;
import com.zmn.plat.model.entity.service.category.ItemCategoryQuery;
import com.zmn.plat.model.entity.service.group.ServiceGroup;
import com.zmn.plat.model.entity.service.item.ServiceItem;
import com.zmn.plat.model.entity.service.item.ServiceItemEditDIO;
import com.zmn.plat.model.entity.service.item.ServiceItemQuery;
import com.zmn.plat.model.entity.service.itemdetail.ItemDetail;
import com.zmn.plat.model.entity.service.tariff.ServiceTariff;
import com.zmn.plat.model.entity.warranty.content.WarrantyContent;
import com.zmn.plat.model.entity.warranty.content.WarrantyContentQuery;
import com.zmn.plat.model.entity.warranty.info.WarrantyInfo;
import com.zmn.plat.model.entity.warranty.info.WarrantyInfoQuery;
import com.zmn.plat.model.vo.product.tariff.item.ProductTariffGroupItemVo;
import com.zmn.plat.model.vo.servcategory.ServAssCategoryVO;
import com.zmn.plat.model.vo.service.item.ServiceItemDetailVO;
import com.zmn.plat.model.vo.service.item.ServiceItemWarrantyInfoVO;
import com.zmn.plat.model.vo.service.item.ServicePageVO;
import com.zmn.plat.model.vo.warranty.WarrantyInfoVO;
import com.zmn.plat.services.interfaces.category.BaseCategoryService;
import com.zmn.plat.services.interfaces.product.ServProductService;
import com.zmn.plat.services.interfaces.product.tariff.item.ProductTariffGroupItemService;
import com.zmn.plat.services.interfaces.servcategory.ServAssCategoryService;
import com.zmn.plat.services.interfaces.servcategory.ServCategoryService;
import com.zmn.plat.services.interfaces.service.category.ItemCategoryService;
import com.zmn.plat.services.interfaces.service.group.ServiceGroupService;
import com.zmn.plat.services.interfaces.service.item.ServiceItemService;
import com.zmn.plat.services.interfaces.service.item.config.ServiceItemTimeConfigService;
import com.zmn.plat.services.interfaces.service.itemdetail.ItemDetailService;
import com.zmn.plat.services.interfaces.service.tariff.ServiceTariffService;
import com.zmn.plat.services.interfaces.warranty.content.WarrantyContentService;
import com.zmn.plat.services.interfaces.warranty.info.WarrantyInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author tanbiao
 * @description
 * @modifier
 * @since 2019/11/27 10:06
 **/
@Service
@Slf4j
public class ServiceItemBServiceImpl implements ServiceItemBService {
    @Resource
    private ServiceItemService faultItemService;
    @Resource
    private ServiceItemTimeConfigService faultItemTimeConfigService;
    @Resource
    private ServiceGroupService faultGroupService;
    @Resource
    private ProductTariffGroupItemService productFaultItemService;
    @Resource
    private ServCategoryService servCategoryService;
    @Resource
    private BaseCategoryService baseCategoryService;
    @Resource
    private ServAssCategoryService servAssCategoryService;
    @Resource
    private ItemCategoryService faultCategoryService;
    @Resource
    private ServiceTariffService faultTariffService;
    @Resource
    private ServProductService servProductService;
    @Resource
    private ChannelTariffBService channelTariffBService;
    @Resource
    private ProductServiceItemPriceBService productFaultItemPriceBService;
    @Resource
    private WarrantyInfoService warrantyInfoService;
    @Resource
    private WarrantyContentService warrantyContentService;
    @Resource
    private ChannelServiceCategoryBService channelServiceCategoryBService;
    @Resource
    private ServServiceTimeBService serviceTimeBService;
    @Resource
    private ItemDetailService  itemDetailService;

    private final static int DEFAULT_CHECK_FEE = 20;
    private final static int DEFAULT_HOUR_FEE = 60;
    private final static int DEFAULT_TRAFFIC_FEE = 25;


    @Override
    public ServiceItemDRO getById(Integer itemId) {
        if (NumberUtil.isNullOrZero(itemId)) {
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }

        ServiceItem item = faultItemService.findByKey(itemId);
        if (Objects.isNull(item)) {
            log.error("item is null.errorCode:{},itemId:{}", PlatErrorCodeDict.ERROR_CODE_PRODUCT_ITEM_NOT_EXIT, itemId);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PRODUCT_ITEM_NOT_EXIT);
        }
        ServiceGroup group = faultGroupService.findByKey(item.getGroupId());
        if (!Objects.isNull(group)) {
            item.setGroupName(group.getGroupName());
        }
        ServiceItemDRO dro = new ServiceItemDRO();
        BeanCopier copier = BeanCopier.create(ServiceItem.class, ServiceItemDRO.class, false);
        copier.copy(item, dro, null);
        return dro;
    }

    @Override
    public ServiceItemDetailVO getByItemIdAndGroupId(Integer itemId, Integer groupId) {
        ServiceItem faultItem;
        ServiceGroup group = new ServiceGroup();
        if (itemId == 0) {
            faultItem = new ServiceItem();
            faultItem.setTrafficFee(DEFAULT_TRAFFIC_FEE);
            faultItem.setCheckFee(DEFAULT_CHECK_FEE);
            faultItem.setHourFee(DEFAULT_HOUR_FEE);
        } else {
            faultItem = faultItemService.findByKey(itemId);
            // 价格可编辑，将分转换为元
            faultItem.setTrafficFee(Objects.isNull(faultItem.getTrafficFee()) ? null : faultItem.getTrafficFee() / GlobalConsts.MONEY_YUAN_FEN_RATE);
            faultItem.setCheckFee(Objects.isNull(faultItem.getCheckFee()) ? null : faultItem.getCheckFee() / GlobalConsts.MONEY_YUAN_FEN_RATE);
            faultItem.setHourFee(Objects.isNull(faultItem.getHourFee()) ? null : faultItem.getHourFee() / GlobalConsts.MONEY_YUAN_FEN_RATE);
            groupId = faultItem.getGroupId();
        }
        if (groupId != 0) {
            group = faultGroupService.findByKey(groupId);
        }
        ServiceTariff faultTariff = faultTariffService.findByKey(group.getTariffId());
        BaseCategory baseCategory = baseCategoryService.findByKey(group.getCategOneId());
        ServCategory servCategory = servCategoryService.findByKey(group.getServCategId());
        faultItem.setGroupId(groupId);
        // 是否存在默认服务项，是否是默认项自己修改自己
        boolean hasDefaultItem = false;
        boolean updateMyself = false;
        ServiceItemQuery query = new ServiceItemQuery();
        query.setGroupId(groupId);
        query.setGeneral(GlobalConsts.YES);
        List<ServiceItem> defaultItemList = faultItemService.listByQuery(query);
        if (!CollectionUtils.isEmpty(defaultItemList)) {
            hasDefaultItem = true;
            ServiceItem defaultItem = defaultItemList.get(0);
            if (defaultItem.getItemId().equals(itemId)) {
                updateMyself = true;
            }
        }
        // 故障项目区分包内保外和状态
        List<ItemCategory> list = getFaultCategorys(faultTariff.getBizType(), faultTariff.getTariffType() == 3 ? 2 : faultTariff.getTariffType(), faultItem);
        ServiceItemDetailVO vo = new ServiceItemDetailVO();
        vo.setFaultItem(faultItem);
        vo.setGroup(group);
        vo.setDefaultItem(hasDefaultItem);
        vo.setUpdateMyself(updateMyself);
        vo.setCategories(list);
        vo.setFaultTariff(faultTariff);
        vo.setBaseCategory(baseCategory);
        vo.setServCategory(servCategory);
        return vo;
    }

    @Override
    public Integer getMaxServiceMinutes(Integer productId, List<Integer> itemIdList, Integer companyId) {
        if (NumberUtil.isNullOrZero(productId) || CollectionUtils.isEmpty(itemIdList)) {
            log.error("参数为空，productId:{},itemIdList:{}", productId, itemIdList);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }
        Integer serviceTime = null;
        if (!NumberUtil.isNullOrZero(companyId)) {
            serviceTime = serviceTimeBService.getServiceMinutesByItemIdAndCompanyId(itemIdList, companyId);
        }
        if (!NumberUtil.isNullOrZero(serviceTime)) {
            return serviceTime;
        }

        List<ServiceItem> itemList = faultItemService.listByItemIds(itemIdList);
        if (CollectionUtils.isEmpty(itemIdList)) {
            log.error("项目不存在，productId:{},itemIdList:{}", productId, itemIdList);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_RESULT_NULL);
        }

        // 过滤配置了服务时长的项目，如果存在没有配置的，需要取前台产品二级分类上配置的服务时长
        List<Integer> serviceMinutes = itemList.stream().filter(e -> Objects.nonNull(e.getServiceMinutes())).map(e -> e.getServiceMinutes()).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(serviceMinutes)) {
            log.info("项目和前台产品二级分类上都没有配置服务时长，返回null，productId:{},itemIdList:{}", productId, itemIdList);
            return GlobalConsts.NONE;
        }

        Integer max = serviceMinutes.stream().collect(Collectors.summarizingInt(Integer::intValue)).getMax();
        return max;
    }

    @Override
    public ServiceItemWarrantyInfoVO getWarrantyInfoByServCategIdAndCategIdAndGroupIdAndItemId(Integer servCategId, Integer categOneId, Integer groupId, Integer itemId) {
        ServiceItem faultItem;
        ServiceGroup group = new ServiceGroup();
        if (itemId == 0) {
            faultItem = new ServiceItem();
        } else {
            faultItem = faultItemService.findByKey(itemId);
            groupId = faultItem.getGroupId();
        }
        if (groupId != 0) {
            group = faultGroupService.findByKey(groupId);
        }
        ServiceTariff faultTariff = faultTariffService.findByKey(group.getTariffId());
        BaseCategory baseCategory = baseCategoryService.findByKey(group.getCategOneId());
        List<BaseCategory> baseCategories = baseCategoryService.listByParentId(categOneId, GlobalConsts.YES);
        ServCategory servCategory = servCategoryService.findByKey(group.getServCategId());
        WarrantyInfoQuery warrantyInfoQuery = new WarrantyInfoQuery();
        warrantyInfoQuery.setItemId(itemId);
        List<WarrantyInfo> warrantyInfos = warrantyInfoService.listByQuery(warrantyInfoQuery);
        WarrantyContentQuery warrantyContentQuery = new WarrantyContentQuery();
        warrantyContentQuery.setBizType(String.valueOf(faultTariff.getBizType()));
        List<WarrantyContent> warrantyContents = warrantyContentService.listByQuery(warrantyContentQuery);
        Map<Integer, String> warrantyContentMap = warrantyContents.stream().collect(Collectors.toMap(item -> item.getWarrantyContentId(), item -> item.getContent(), (p, u) -> p));
        List<WarrantyInfoVO> warrantyInfoVOS = new ArrayList<>();
        warrantyInfos.forEach(e -> {
            WarrantyInfoVO warrantyInfoVO = new WarrantyInfoVO();
            BeanUtils.copyProperties(e, warrantyInfoVO);
            warrantyInfoVO.setRuleName(WarrantyRuleEnum.of(e.getRuleId()).getName());
            warrantyInfoVO.setWarrantyContentStrShow(getWarrantyContentStrShow(e.getWarrantyContentIdStr(), warrantyContentMap));
            warrantyInfoVO.setWarrantyDurationStrShow(getWarrantyDurationStrShow(e.getWarrantyDurationStr()));
            warrantyInfoVOS.add(warrantyInfoVO);
        });
        faultItem.setGroupId(groupId);
        ServiceItemWarrantyInfoVO vo = new ServiceItemWarrantyInfoVO();
        vo.setFaultItem(faultItem);
        vo.setGroup(group);
        vo.setFaultTariff(faultTariff);
        vo.setBaseCategory(baseCategory);
        vo.setServCategory(servCategory);
        vo.setBaseCategories(baseCategories);
        vo.setWarrantyInfoVOS(warrantyInfoVOS);
        return vo;
    }

    @Override
    public ServiceItemWarrantyInfoVO getBatchWarrantyInfoByTariffIdAndServCategIdAndCategOneId(Integer tariffId, Integer servCategId, Integer categOneId) {
        ServiceTariff faultTariff = faultTariffService.findByKey(tariffId);
        BaseCategory baseCategory = baseCategoryService.findByKey(categOneId);
        List<BaseCategory> baseCategories = baseCategoryService.listByParentId(categOneId, GlobalConsts.YES);
        ServCategory servCategory = servCategoryService.findByKey(servCategId);
        ServiceItemWarrantyInfoVO vo = new ServiceItemWarrantyInfoVO();
        vo.setFaultTariff(faultTariff);
        vo.setBaseCategory(baseCategory);
        vo.setServCategory(servCategory);
        vo.setBaseCategories(baseCategories);
        vo.setWarrantyInfoVOS(new ArrayList<>());
        return vo;
    }

    @Override
    public ServicePageVO listPageByQuery(ServTariffAssCategoryQuery query) {
        List<ServAssCategoryVO> items = servAssCategoryService.listPageGroupByCategOneId(query);
        ServCategory servQuery = new ServCategory();
        servQuery.setStatus(GlobalConsts.YES);
        List<ServCategory> servCategories = servCategoryService.listByQuery(servQuery);
        // 服务分类需要产品一级分类联动
        List<BaseCategory> baseCategories = new ArrayList<>();
        if (NumberUtil.isNullOrZero(query.getServCategId())) {
            BaseCategoryQuery baseCategoryQuery = new BaseCategoryQuery();
            baseCategoryQuery.setShowType(ProductConsts.ERP_PRODUCT_TYPE);
            baseCategoryQuery.setLevel(baseCategoryQuery.LEVEL_1);
            baseCategoryQuery.setStatus(GlobalConsts.YES);
            baseCategories = baseCategoryService.listByQuery(baseCategoryQuery);
        } else {
            baseCategories = servAssCategoryService.findCategoryOneByServIdAndShowType(query.getServCategId(), ProductConsts.ERP_PRODUCT_TYPE);
            baseCategories = baseCategories.stream().filter(e -> e.getStatus().equals(GlobalConsts.YES)).collect(Collectors.toList());
        }
        ServicePageVO pageVO = new ServicePageVO();
        pageVO.setItems(items);
        pageVO.setBaseCategories(baseCategories);
        pageVO.setServCategories(servCategories);
        return pageVO;
    }

    @Override
    public List<ProductServiceItemDRO> listByDIO(ServiceItemServPriceDIO servItemPriceDIO) {
        // 兼容处理，后期删除
        if (NumberUtil.isPositiveInteger(servItemPriceDIO.getKeepType()) && !NumberUtil.isPositiveInteger(servItemPriceDIO.getBizType())) {
            servItemPriceDIO.setBizType(servItemPriceDIO.getKeepType());
        }

        if (Objects.isNull(servItemPriceDIO) || NumberUtil.isNullOrZero(servItemPriceDIO.getProductId()) || NumberUtil.isNullOrZero(servItemPriceDIO.getChannelId())) {
            log.error("param error,servItemPriceDIO={}", servItemPriceDIO);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }

        ServProduct servProduct = servProductService.findByKey(servItemPriceDIO.getProductId());
        if (Objects.isNull(servProduct)) {
            log.error("产品不存在,servItemPriceDIO={},errorCode:{}", servItemPriceDIO, PlatErrorCodeDict.ERROR_CODE_SERVICE_PRODUCT_NULL);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_SERVICE_PRODUCT_NULL);
        }
        ServiceTariff tariff = null;

        // 根据渠道ID和产品id查询渠道配置的价格表
        if (NumberUtil.isPositiveInteger(servItemPriceDIO.getChannelId()) || NumberUtil.isPositiveInteger(servItemPriceDIO.getBizType())) {
            Integer channelId = channelServiceCategoryBService.getAvailableCategoryChannelId(servItemPriceDIO.getChannelId());
            servItemPriceDIO.setChannelId(channelId);
            tariff = channelTariffBService.getTariffIdByProductIdAndChannelIdAndBizTypeAndTariffType(servItemPriceDIO.getProductId(), servItemPriceDIO.getChannelId(), servItemPriceDIO.getBizType(),
                    servItemPriceDIO.getTariffType());
        }
        // 查询特殊服务项
        List<ProductServiceItemDRO> dros = Collections.emptyList();
        if (!CollectionUtils.isEmpty(servItemPriceDIO.getIdList())) {
            dros = this.getSpecialItemDRO(servItemPriceDIO.getIdList());
        }

        if (Objects.isNull(tariff)) {
            log.error("价格表不存在,servItemPriceDIO={},errorCode:{}", servItemPriceDIO, PlatErrorCodeDict.ERROR_CODE_SERVICE_TARIFF_NULL);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_SERVICE_TARIFF_NULL);
        }

        List<ProductServiceItemDRO> servServiceItemDROS = this.getNomalItemDRO(tariff, servItemPriceDIO);

        if (!CollectionUtils.isEmpty(dros)) {
            servServiceItemDROS.addAll(dros);
        }
        return servServiceItemDROS;
    }

    @Cacheable(key = "'service:list:special:item:ids:' + #p0", cacheNames = "redis5m")
    public List<ProductServiceItemDRO> getSpecialItemDRO(List<Integer> itemIdList) {
        // 特殊项目，id为负数，提前初始化的数据
        List<ProductTariffGroupItemVo> servServiceItemVOS = productFaultItemService.listSpecialItemByIdList(itemIdList);
        BeanCopier copier = BeanCopier.create(ProductTariffGroupItemVo.class, ProductServiceItemDRO.class, false);
        List<ProductServiceItemDRO> dros = servServiceItemVOS.stream().map(itemVO -> {
            ProductServiceItemDRO serviceItemDRO1 = new ProductServiceItemDRO();
            copier.copy(itemVO, serviceItemDRO1, null);
            serviceItemDRO1.setGroupName(ProductConsts.SERVICE_ITEM_COMMON_ADJUST_GROUP_NAME);
            serviceItemDRO1.setGroupId(ProductConsts.SERVICE_ITEM_COMMON_ADJUST_GROUP_ID);
            return serviceItemDRO1;
        }).collect(Collectors.toList());
        return dros;
    }

    // @Cacheable(value={"faultTariff","servItemDIO"},key = "'service:list:noraml:item:standard:' + #faultTariff.tariffId+ ':ratio:' + #p1",
    // cacheNames = "redis5m")
    public List<ProductServiceItemDRO> getNomalItemDRO(ServiceTariff faultTariff, ServiceItemServDIO servItemDIO) {
        // 兼容处理，后期删除
        if (NumberUtil.isPositiveInteger(servItemDIO.getKeepType()) && !NumberUtil.isPositiveInteger(servItemDIO.getBizType())) {
            servItemDIO.setBizType(servItemDIO.getKeepType());
        }
        // 根据服务组组合查询服务项,需要区分价格表计价方式，城市定价和系数定价的计算方式不同
        List<ProductTariffGroupItemVo> servServiceItemVOList =
                productFaultItemService.listByTariffIdAndCityIdAndProductId(faultTariff.getTariffId(), servItemDIO.getCityId(), servItemDIO.getProductId());
        // 城市定价只考虑品牌系数
        BeanCopier copier = BeanCopier.create(ProductTariffGroupItemVo.class, ProductServiceItemDRO.class, false);
        List<ProductServiceItemDRO> servServiceItemDROS = new ArrayList<>();

        // 入参传入分公司时需要取分公司的服务时长，没有配置分公司服务时长则取通用时长
        List<Integer> itemIds = servServiceItemVOList.stream().map(ProductTariffGroupItemVo::getItemId).collect(Collectors.toList());
        Map<Integer, Integer> maps = serviceTimeBService.setServiceDuration(itemIds, servItemDIO.getCompanyId());

        for (ProductTariffGroupItemVo e : servServiceItemVOList) {
            ProductServiceItemDRO serviceItemDRO = new ProductServiceItemDRO();
            productFaultItemPriceBService.calPriceDetail(e, new ItemPriceCalDTO(servItemDIO.getChannelId(), servItemDIO.getCityId(), servItemDIO.getBrandId(), servItemDIO.getBizType(), null));
            copier.copy(e, serviceItemDRO, null);
            if (CollectionUtil.isNotNullOrEmpty(maps)) {
                serviceItemDRO.setServiceMinutes(NumberUtil.isNullOrZero(maps.get(e.getItemId())) ? e.getServiceMinutes() : maps.get(e.getItemId()));
            }
            servServiceItemDROS.add(serviceItemDRO);
        }
        return servServiceItemDROS;
    }

    @Override
    @SuppressWarnings("Duplicates")
    public List<ProductServiceItemDRO> listByCategIdList(List<Integer> categIds, Integer companyId) {
        if (CollectionUtils.isEmpty(categIds)) {
            log.error("categIds is null,categIds={}", categIds);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }

        List<ProductTariffGroupItemVo> servServiceItemVOS = productFaultItemService.listSpecialItemByIdList(categIds);

        // 入参传入分公司时需要取分公司的服务时长，没有配置分公司服务时长则取通用时长
        List<Integer> itemIds = servServiceItemVOS.stream().map(ProductTariffGroupItemVo::getItemId).collect(Collectors.toList());
        Map<Integer, Integer> maps = serviceTimeBService.setServiceDuration(itemIds, companyId);

        BeanCopier copier = BeanCopier.create(ProductTariffGroupItemVo.class, ProductServiceItemDRO.class, false);
        List<ProductServiceItemDRO> dros = servServiceItemVOS.stream().map(itemVO -> {
            ProductServiceItemDRO serviceItemDRO1 = new ProductServiceItemDRO();
            copier.copy(itemVO, serviceItemDRO1, null);
            serviceItemDRO1.setGroupName(ProductConsts.SERVICE_ITEM_COMMON_ADJUST_GROUP_NAME);
            serviceItemDRO1.setGroupId(ProductConsts.SERVICE_ITEM_COMMON_ADJUST_GROUP_ID);
            // 设置服务时长
            if (CollectionUtil.isNotNullOrEmpty(maps)) {
                serviceItemDRO1.setServiceMinutes(NumberUtil.isNullOrZero(maps.get(serviceItemDRO1.getItemId())) ? serviceItemDRO1.getServiceMinutes() : maps.get(serviceItemDRO1.getItemId()));
            }
            return serviceItemDRO1;
        }).collect(Collectors.toList());
        return dros;
    }

    @Override
    public List<ServiceItemDRO> listByGroupId(Integer groupId) {
        if (!NumberUtil.isPositiveInteger(groupId)) {
            log.error("listByGroupId 参数不合法，groupId={}", groupId);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }
        List<ServiceItem> list = faultItemService.listByGroupIds(Arrays.asList(groupId));
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        BeanCopier copier = BeanCopier.create(ServiceItem.class, ServiceItemDRO.class, false);
        List<ServiceItemDRO> droList = list.stream().map(e -> {
            ServiceItemDRO serviceItemDRO = new ServiceItemDRO();
            copier.copy(e, serviceItemDRO, null);
            return serviceItemDRO;
        }).collect(Collectors.toList());
        return droList;
    }

    @Override
    public List<ServiceItemDRO> listByDIO(ServiceItemDIO query) {
        if (Objects.isNull(query)) {
            log.error("listByDIO查询参数为空");
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }

        BeanCopier copierQuery = BeanCopier.create(ServiceItemDIO.class, ServiceItemQuery.class, false);
        ServiceItemQuery itemQuery = new ServiceItemQuery();
        copierQuery.copy(query, itemQuery, null);
        List<ServiceItem> list = faultItemService.listByQuery(itemQuery);
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        BeanCopier copier = BeanCopier.create(ServiceItem.class, ServiceItemDRO.class, false);
        List<ServiceItemDRO> droList = list.stream().map(e -> {
            ServiceItemDRO serviceItemDRO = new ServiceItemDRO();
            copier.copy(e, serviceItemDRO, null);
            return serviceItemDRO;
        }).collect(Collectors.toList());
        return droList;
    }

    @Override
    public MaxAveragePriceDRO getMaxAveragePriceByChannelIdAndTypeAndCityIdAndProductId(ServiceItemServDIO dio) {
        // 兼容处理，后期删除
        if (NumberUtil.isPositiveInteger(dio.getKeepType()) && !NumberUtil.isPositiveInteger(dio.getBizType())) {
            dio.setBizType(dio.getKeepType());
        }

        if (NumberUtil.isNullOrZero(dio.getChannelId()) || NumberUtil.isNullOrZero(dio.getBizType()) || NumberUtil.isNullOrZero(dio.getChannelId()) || NumberUtil.isNullOrZero(dio.getProductId())
                || NumberUtil.isNullOrZero(dio.getTariffType())) {
            log.error("getMaxAveragePriceByChannelIdAndTypeAndCityIdAndProductId查询参数有误，dio={}", dio);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }

        List<ProductServiceItemDRO> servItemPriceDROS = this.listByChannelIdAndTypeAndCityIdAndProductId(dio);
        List<Integer> priceList =
                servItemPriceDROS.stream().filter(servItemPriceDRO -> NumberUtil.isPositiveInteger(servItemPriceDRO.getPrice())).map(ProductServiceItemDRO::getPrice).collect(Collectors.toList());
        MaxAveragePriceDRO maxAveragePriceDRO = new MaxAveragePriceDRO();
        if (CollectionUtils.isEmpty(priceList)) {
            maxAveragePriceDRO.setAverage(ProductDict.ZERO);
            maxAveragePriceDRO.setMax(ProductDict.ZERO);
            return maxAveragePriceDRO;
        }

        int total = 0;
        for (int i = 0; i < priceList.size(); i++) {
            total += priceList.get(i);
        }
        total = total / ProductDict.HUNDRED;
        int price = Math.round(total / servItemPriceDROS.size());
        maxAveragePriceDRO.setMax(Collections.max(priceList));
        maxAveragePriceDRO.setAverage(price * ProductDict.HUNDRED);
        return maxAveragePriceDRO;
    }

    @Override
    public ProductPriceTableDRO getProductDefaultPriceTable(ServiceItemServDIO faultItemServDIO) {
        // 兼容处理，后期删除
        if (NumberUtil.isPositiveInteger(faultItemServDIO.getKeepType()) && !NumberUtil.isPositiveInteger(faultItemServDIO.getBizType())) {
            faultItemServDIO.setBizType(faultItemServDIO.getKeepType());
        }

        if (NumberUtil.isNullOrZero(faultItemServDIO.getBizType()) || NumberUtil.isNullOrZero(faultItemServDIO.getChannelId()) || NumberUtil.isNullOrZero(faultItemServDIO.getTariffType())
                || NumberUtil.isNullOrZero(faultItemServDIO.getProductId())) {
            log.error("getProductDefaultPriceTable paras is not validate.faultItemServDIO={}", faultItemServDIO);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }
        ProductPriceTableDRO dto = new ProductPriceTableDRO();
        ServProduct servProduct = servProductService.findByKey(faultItemServDIO.getProductId());
        if (Objects.isNull(servProduct)) {
            log.error("产品不存在.faultItemServDIO={},errorCode:{}", faultItemServDIO, PlatErrorCodeDict.ERROR_CODE_SERVICE_PRODUCT_NULL);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_SERVICE_PRODUCT_NULL);
        }
        ServiceTariff tariff = null;

        // 根据渠道ID和产品id查询渠道配置的价格表
        if (NumberUtil.isPositiveInteger(faultItemServDIO.getChannelId()) || NumberUtil.isPositiveInteger(faultItemServDIO.getBizType())) {
            Integer channelId = channelServiceCategoryBService.getAvailableCategoryChannelId(faultItemServDIO.getChannelId());
            faultItemServDIO.setChannelId(channelId);
            tariff = channelTariffBService.getTariffIdByProductIdAndChannelIdAndBizTypeAndTariffType(faultItemServDIO.getProductId(), faultItemServDIO.getChannelId(), faultItemServDIO.getBizType(),
                    faultItemServDIO.getTariffType());
        }
        if (Objects.isNull(tariff)) {
            log.error("价格表不存在.faultItemServDIO={},errorCode:{}", faultItemServDIO, PlatErrorCodeDict.ERROR_CODE_SERVICE_TARIFF_NULL);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_SERVICE_TARIFF_NULL);
        }

        dto.setPriceTableId(tariff.getTariffId());
        dto.setPriceTableName(tariff.getTariffName());
        dto.setServiceGroups(new HashMap<>());
        List<ProductServiceItemDRO> dros = getNomalItemDRO(tariff, faultItemServDIO);
        dros.stream().forEach(e -> {
            List<ProductServiceItemDRO> items = dto.getServiceGroups().get(e.getGroupName());
            if (CollectionUtils.isEmpty(items)) {
                items = new ArrayList<ProductServiceItemDRO>();
                dto.getServiceGroups().put(e.getGroupName(), items);
            }
            items.add(e);
        });
        return dto;
    }

    @Override
    public List<ProductServiceItemDRO> listByChannelIdAndTypeAndCityIdAndProductId(ServiceItemServDIO dio) {
        // 兼容处理，后期删除
        if (NumberUtil.isPositiveInteger(dio.getKeepType()) && !NumberUtil.isPositiveInteger(dio.getBizType())) {
            dio.setBizType(dio.getKeepType());
        }

        if (NumberUtil.isNullOrZero(dio.getChannelId()) || NumberUtil.isNullOrZero(dio.getBizType()) || NumberUtil.isNullOrZero(dio.getCityId()) || NumberUtil.isNullOrZero(dio.getProductId())
                || NumberUtil.isNullOrZero(dio.getTariffType())) {
            log.error("listByChannelIdAndTypeAndCityIdAndProductId params is not validate.dio={}", dio);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_PANAM_NULL);
        }

        // List<ProductServiceItemDRO> list = Collections.emptyList();
        ServProduct servProduct = servProductService.findByKey(dio.getProductId());
        if (Objects.isNull(servProduct)) {
            log.error("产品不存在.faultItemServDIO={}", dio);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_SERVICE_PRODUCT_NULL);
        }
        ServiceTariff tariff = null;

        // 根据渠道ID和产品id查询渠道配置的价格表
        if (NumberUtil.isPositiveInteger(dio.getChannelId()) || NumberUtil.isPositiveInteger(dio.getBizType())) {
            Integer channelId = channelServiceCategoryBService.getAvailableCategoryChannelId(dio.getChannelId());
            dio.setChannelId(channelId);
            tariff = channelTariffBService.getTariffIdByProductIdAndChannelIdAndBizTypeAndTariffType(dio.getProductId(), dio.getChannelId(), dio.getBizType(), dio.getTariffType());
        }
        if (Objects.isNull(tariff)) {
            log.error("价格表不存在.faultItemServDIO={},errorCode:{}", dio, PlatErrorCodeDict.ERROR_CODE_SERVICE_TARIFF_NULL);
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_SERVICE_TARIFF_NULL);
        }
        List<ProductServiceItemDRO> servServiceItemDROS = this.getNomalItemDRO(tariff, dio);
        return servServiceItemDROS;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer addEdit(ServiceItemEditDIO faultItemDIO, String operator) {
        ServiceItem faultItem = new ServiceItem();
        BeanUtils.copyProperties(faultItemDIO, faultItem);
        Date now = DateUtil.getNow();
        Integer itemId = faultItem.getItemId();
        Integer result = -1;

        setFaultItemByCondition(faultItem);
        // 同一分组下存在多个默认服务项，保留当前默认服务项，重置其他默认服务项为非默认项
        if (faultItem.getGeneral().equals(GlobalConsts.YES)) {
            ServiceItemQuery query = new ServiceItemQuery();
            query.setGroupId(faultItem.getGroupId());
            query.setGeneral(GlobalConsts.YES);
            List<ServiceItem> defaultItems = faultItemService.listByQuery(query);
            if (!CollectionUtils.isEmpty(defaultItems)) {
                // 只存在一个默认服务项
                ServiceItem item = defaultItems.get(0);
                if (NumberUtil.isNullOrZero(itemId) || !Objects.equals(item.getItemId(), itemId)) {
                    item.setGeneral(GlobalConsts.NO);
                    faultItemService.updateByKey(item);
                }
            }
        }

//        faultItem.setHourFee(faultItem.getHourFee()==0?null:faultItem.getHourFee());
//        faultItem.setTrafficFee(faultItem.getTrafficFee()==0?null:faultItem.getTrafficFee());
//        faultItem.setCheckFee(faultItem.getCheckFee()==0?null:faultItem.getCheckFee());

        // 检查默认项修改之后会不会导致价格表出现没有默认项或者超过一个默认项
        checkHasDefaultItemRelated(faultItem);
        if (NumberUtil.isNullOrZero(itemId)) {
            faultItem.setCreater(operator);
            faultItem.setCreateTime(now);
            result = faultItemService.insert(faultItem);
        } else {
            faultItem.setUpdater(operator);
            faultItem.setUpdateTime(now);
            result = updateFaultItemAndPrice(faultItem);
        }
        // 更新操作时间
        ServiceGroup group = faultGroupService.findByKey(faultItem.getGroupId());
        ServAssCategoryQuery servAssCategoryQuery = new ServAssCategoryQuery();
        servAssCategoryQuery.setFaultUpdater(operator);
        servAssCategoryQuery.setFaultUpdateTime(now);
        servAssCategoryQuery.setServCategId(group.getServCategId());
        servAssCategoryQuery.setCategOneId(group.getCategOneId());
        servAssCategoryService.updateFaultUpdaterAndTimeByServCategIdAndCategOneId(servAssCategoryQuery);
        /**
         * 添加计价器3.0的基础价格
         */
        ItemDetail itemDetail = itemDetailService.findById(faultItem.getItemId());
        if (!StringUtil.isBlank(faultItemDIO.getAcceptProjectList()) ||
                !StringUtil.isBlank(faultItemDIO.getServiceContentList()) ||
                !StringUtil.isBlank(faultItemDIO.getFaultList()) ||
                NumberUtil.isNotNullOrZero(faultItemDIO.getMaintainDifficulty())) {
            if (itemDetail == null) {
                itemDetail = new ItemDetail();
            }
            itemDetail.setAcceptProjectList(faultItemDIO.getAcceptProjectList());
            itemDetail.setServiceContentList(faultItemDIO.getServiceContentList());
            itemDetail.setFaultList(faultItemDIO.getFaultList());
            itemDetail.setMaintainDifficulty(faultItemDIO.getMaintainDifficulty());
            if (NumberUtil.isNullOrZero(itemDetail.getItemId())) {
                itemDetail.setItemId(faultItem.getItemId());
                itemDetail.setCreater(operator);
                itemDetail.setCreateTime(new Date());
                itemDetailService.insert(itemDetail);
            } else {
                itemDetail.setUpdater(operator);
                itemDetail.setUpdateTime(new Date());
                itemDetailService.updateByKey(itemDetail);
            }
        }
        faultItemDIO.setItemId(faultItem.getItemId());
        return result;
    }

    @Override
    public void batchAddEditWarrantyInfo(WarrantyInfoVO warrantyInfoVO, String operator) {
        Date now = DateUtil.getNow();

        warrantyInfoService.deleteByBizTypeAndCategIdsAndItemIds(warrantyInfoVO.getBizType(), warrantyInfoVO.getCategIds(), warrantyInfoVO.getItemIds());
        List<WarrantyInfo> warrantyInfos = new ArrayList<>();
        for (int i = 0; i < warrantyInfoVO.getItemIds().size(); i++) {
            for (int j = 0; j < warrantyInfoVO.getCategIds().size(); j++) {
                WarrantyInfo warrantyInfo = new WarrantyInfo();
                BeanUtils.copyProperties(warrantyInfoVO, warrantyInfo);
                warrantyInfo.setCategId(warrantyInfoVO.getCategIds().get(j));
                warrantyInfo.setItemId(warrantyInfoVO.getItemIds().get(i));
                warrantyInfo.setCreater(operator);
                warrantyInfo.setUpdater(operator);
                warrantyInfo.setCreateTime(now);
                warrantyInfo.setUpdateTime(now);
                warrantyInfos.add(warrantyInfo);
            }
        }

        if (!CollectionUtils.isEmpty(warrantyInfos)) {
            warrantyInfoService.insertBatch(warrantyInfos);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer deleteByKey(Integer itemId) {
        ServiceItem item = faultItemService.findByKey(itemId);
        if (Objects.isNull(item)) {
            log.error("deleteByKey item is null");
            throw new PlatException("故障项目数据不存在");
        }
        if (!Objects.equals(item.getStatus(), GlobalConsts.NO)) {
            log.error("deleteByKey item status is on,can't delete");
            throw new PlatException("只能删除停用状态的故障项");
        }
        // 删除服务项
        faultItemService.deleteByKey(itemId);
        productFaultItemService.deleteByItemId(itemId);

        // 删除保修信息
        warrantyInfoService.deleteByItemId(itemId);
        // 删除时间配置信息
        Integer result = faultItemTimeConfigService.deleteByItemId(itemId);

        return result;
    }

    private void setFaultItemByCondition(ServiceItem item) {
        if (Objects.isNull(item.getPriceStandard())) {
            log.error("item priceStandard is null");
            throw new PlatException("一口价类型参数不合法");
        }
        // 1.非一口价，交通费工时费包干费，技术服务费，是否区分明细置为空
        if (Objects.equals(item.getPriceStandard(), GlobalConsts.NO)) {
            setNullForDetailTypeOne(item);
            setNullForDetailTypeTwo(item);
            item.setPriceSplit(GlobalConsts.NO);
            item.setPriceSplitType(null);
        }
        // 一口价不区分明细：交通费工时费包干费，技术服务费置为空
        if (Objects.equals(item.getPriceStandard(), GlobalConsts.YES) && Objects.equals(item.getPriceSplit(), GlobalConsts.NO)) {
            setNullForDetailTypeOne(item);
            setNullForDetailTypeTwo(item);
            item.setPriceSplitType(null);
        }
        // 一口价区分明细，明细类型分类两种
        if (Objects.equals(item.getPriceStandard(), GlobalConsts.YES) && Objects.equals(item.getPriceSplit(), GlobalConsts.YES)) {
            // 类型1，类型二的相应数据置空
            if (!NumberUtil.isNullOrZero(item.getPriceSplitType())) {
                if (Objects.equals(item.getPriceSplitType(), GlobalConsts.NO)) {
                    setNullForDetailTypeOne(item);
                } else if (Objects.equals(item.getPriceSplitType(), GlobalConsts.YES)) {
                    setNullForDetailTypeTwo(item);
                } else {
                    throw new PlatException("明细类型参数不合法");
                }
            }
        }
    }

    /**
     * 明细类型为1的时候需要置空的数据
     *
     * @param item
     * @return void
     * @author tanbiao
     * @modifier
     * @since 2020/8/4
     */
    private void setNullForDetailTypeOne(ServiceItem item) {
        item.setMaterialFee(null);
        item.setNumberStep(null);
        item.setNumberStepDown(null);
        item.setBaseDiscount(null);
    }

    /**
     * 明细类型为2的时候需要置空的数据
     *
     * @param item
     * @return void
     * @author tanbiao
     * @modifier
     * @since 2020/8/4
     */
    private void setNullForDetailTypeTwo(ServiceItem item) {
        item.setTrafficFee(null);
        item.setHourFee(null);
        item.setPartRatio(null);
        item.setArtRatio(null);
        item.setGuaranteeRatio(null);
        item.setCheckFee(null);
        item.setServiceRatio(null);
    }

    private List<ItemCategory> getFaultCategorys(Integer bizType, Integer categType, ServiceItem faultItem) {
        // 故障类型,区分保内保外，同时加载启用状态的数据
        ItemCategoryQuery faultCategoryQuery = new ItemCategoryQuery();
        faultCategoryQuery.setStatus(GlobalConsts.YES);
        faultCategoryQuery.setBizType(bizType);
        faultCategoryQuery.setCategType(categType);
        List<ItemCategory> categories = faultCategoryService.listByQuery(faultCategoryQuery);
        if (!Objects.isNull(faultItem.getCategId())) {
            ItemCategory category = faultCategoryService.findByKey(faultItem.getCategId());
            if (category.getStatus().equals(GlobalConsts.NO)) {
                categories.add(category);
                Collections.sort(categories);
            }
        }
        return categories;
    }

    /**
     * 功能描述 ：配件包干费需要检查是否合乎要求，合乎要求需要修改产品价格表价格
     *
     * @param
     * @return void
     * @author tanbiao
     * @modifier
     * @since 2019/12/6
     */
    private Integer updateFaultItemAndPrice(ServiceItem faultItem) {
        ServiceItem item = faultItemService.findByKey(faultItem.getItemId());

        //三个固定费用是否有变化，针对后期加入的检测费的兼容处理
        boolean isStaticFeeChanged = !Objects.equals(faultItem.getTrafficFee(), item.getTrafficFee()) || !Objects.equals(faultItem.getHourFee(), item.getHourFee())
                || !Objects.equals(faultItem.getCheckFee(), item.getCheckFee());
        // 修改配件比例需要同步修改价格表
        boolean isRatioChanged = !Objects.equals(faultItem.getPartRatio() == null ? null : faultItem.getPartRatio().setScale(2), item.getPartRatio())
                || !Objects.equals(faultItem.getArtRatio() == null ? null : faultItem.getArtRatio().setScale(2), item.getArtRatio())
                || !Objects.equals(faultItem.getGuaranteeRatio() == null ? null : faultItem.getGuaranteeRatio().setScale(2), item.getGuaranteeRatio());
        boolean isPriceStandardChanged = !Objects.equals(faultItem.getPriceStandard(), item.getPriceStandard());
        // 两者相等()的情况下，不用修改价格表
        if (isStaticFeeChanged || isRatioChanged || isPriceStandardChanged) {
            List<Integer> productFaultItems = new ArrayList<>();
            ProductTariffGroupItemQuery productFaultItemQuery = new ProductTariffGroupItemQuery();
            productFaultItemQuery.setItemId(faultItem.getItemId());
            List<ProductTariffGroupItemVo> list = productFaultItemService.listItemByQuery(productFaultItemQuery);
            if (!CollectionUtils.isEmpty(list)) {
                Integer fee = null;
                Integer partRatio = null;
                Integer artRatio = null;
                Integer guaranteeRatio = null;
                // 配件包干费和工艺费占比不为空，检查比例修改之后是否会造成影响（一口价区分明细）
                if (Objects.nonNull(faultItem.getPartRatio()) && Objects.nonNull(faultItem.getArtRatio()) && Objects.nonNull(faultItem.getGuaranteeRatio())) {
                    fee = faultItem.getHourFee() + faultItem.getTrafficFee() + faultItem.getCheckFee();
                    partRatio = faultItem.getPartRatio().intValue();
                    artRatio = faultItem.getArtRatio().intValue();
                    guaranteeRatio = faultItem.getGuaranteeRatio().intValue();
                    StringBuilder message = new StringBuilder();
                    for (ProductTariffGroupItemVo vo : list) {
                        // 没有设置销售价不存在比例大小问题
                        if (Objects.isNull(vo.getPrice())) {
                            continue;
                        }
                        // 销售价
                        BigDecimal price = new BigDecimal(vo.getPrice());
                        // 配件费
                        BigDecimal partRatioPrice = price.multiply(faultItem.getPartRatio()).divide(new BigDecimal(GlobalConsts.MONEY_YUAN_FEN_RATE));
                        BigDecimal artRatioPrice = price.multiply(faultItem.getArtRatio()).divide(new BigDecimal(GlobalConsts.MONEY_YUAN_FEN_RATE));
                        BigDecimal guaranteeRatioPrice = price.multiply(faultItem.getGuaranteeRatio()).divide(new BigDecimal(GlobalConsts.MONEY_YUAN_FEN_RATE));
                        // 技术服务费
                        BigDecimal tecPrice = price.subtract(partRatioPrice).subtract(artRatioPrice).subtract(guaranteeRatioPrice).subtract(new BigDecimal(fee));
                        if (tecPrice.compareTo(BigDecimal.ZERO) < 0) {
                            message.append("产品【").append(vo.getProductName()).append("】的价格表【").append(vo.getTariffName()).append("】的故障项【").append(vo.getItemName()).append("】技术服务费小于0<br>");
                        } else {
                            productFaultItems.add(vo.getRelateId());
                        }
                    }
                    if (message.length() > 0) {
                        StringBuilder errorMessage = new StringBuilder("修改之后将导致:<br>");
                        throw new PlatException(errorMessage.append(message).toString());
                    }
                }
            }
        }
        Integer result = faultItemService.updateByKey(faultItem);
        return result;
    }

    /**
     * 功能描述 :如果价格表已经关联了一个默认项，那么不允许再添加或者修改一个默认项 1.修改自己不修改默认项，不做变化 2.修改自己同时从非默认到默认，检查 3.修改自己从默认到非默认检查 4.新增非默认不做检查 5.新增默认检查是否产品已存在默认项目
     *
     * @param faultItem
     * @return void
     * @author tanbiao
     * @modifier
     * @since 2019/12/6
     */
    private void checkHasDefaultItemRelated(ServiceItem faultItem) {
        // 1.修改自己不修改默认项，不做变化
        if (!Objects.isNull(faultItem.getItemId())) {
            ServiceItem oldItem = faultItemService.findByKey(faultItem.getItemId());
            if (oldItem.getGeneral().equals(faultItem.getGeneral())) {
                return;
            }
        }
        // 4.新增非默认不做检查
        if (faultItem.getItemId() == null && faultItem.getGeneral().equals(GlobalConsts.NO)) {
            return;
        }
        // 根据分组查询和该分组有关联的所有产品价格表
        List<ProductTariffGroupItemVo> relations = productFaultItemService.listByGroupId(faultItem.getGroupId(), faultItem.getTariffId());
        if (CollectionUtils.isEmpty(relations)) {
            return;
        }
        // 按照产品和价格表两个维度进行分组
        Map<String, List<ProductTariffGroupItemVo>> productTaffMap =
                relations.stream().collect(Collectors.groupingBy(e -> e.getProductId() + "_" + e.getTariffId() + "_" + e.getProductName() + "_" + e.getTariffName()));
        if (Objects.isNull(faultItem.getItemId())) {
            ProductTariffGroupItemVo vo = new ProductTariffGroupItemVo();
            BeanUtils.copyProperties(faultItem, vo);
            productTaffMap.forEach((k, v) -> v.add(vo));
        } else {
            productTaffMap.forEach((k, v) -> {
                Optional<ProductTariffGroupItemVo> option = v.stream().filter(e -> e.getItemId().equals(faultItem.getItemId())).findFirst();
                if (option.isPresent()) {
                    option.get().setGeneral(faultItem.getGeneral());
                }
            });
        }
        // 检查修改或者新增之后是否会导致出现多个默认项
        StringBuilder message = new StringBuilder();
        for (Map.Entry<String, List<ProductTariffGroupItemVo>> entry : productTaffMap.entrySet()) {
            List<ProductTariffGroupItemVo> list = entry.getValue();
            String productName = entry.getKey().split("_")[2];
            String tarrName = entry.getKey().split("_")[3];
            List generalList = list.stream().filter(e -> e.getGeneral().equals(GlobalConsts.YES)).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(generalList) && generalList.size() > 1) {
                message.append("产品【").append(productName).append("】的价格表【").append(tarrName).append("】默认项超过一个<br>");
            }
        }
        if (message.length() > 0) {
            StringBuilder errorMessage = new StringBuilder("修改之后将导致:<br>");
            throw new PlatException(errorMessage.append(message).toString());
        }
    }

    @SuppressWarnings("Duplicates")
    private String getWarrantyDurationStrShow(String warrantyDurationStr) {
        String result = "";
        if (StringUtil.isBlank(warrantyDurationStr)) {
            return result;
        }

        warrantyDurationStr = trimBothEndsChars(warrantyDurationStr, "\\$");
        List<Integer> plats = Arrays.stream(warrantyDurationStr.split("\\$")).map(e -> Integer.parseInt(e)).collect(Collectors.toList());
        StringBuilder stringBulider = new StringBuilder();
        plats.forEach(e -> stringBulider.append(e).append("天;"));
        return stringBulider.deleteCharAt(stringBulider.length() - 1).toString();
    }

    @SuppressWarnings("Duplicates")
    private String getWarrantyContentStrShow(String warrantyContentStr, Map<Integer, String> kvMap) {
        String result = "";
        if (StringUtil.isBlank(warrantyContentStr)) {
            return result;
        }

        warrantyContentStr = trimBothEndsChars(warrantyContentStr, "\\$");
        List<Integer> plats = Arrays.stream(warrantyContentStr.split("\\$")).map(e -> Integer.parseInt(e)).collect(Collectors.toList());
        StringBuilder stringBulider = new StringBuilder();
        plats.forEach(e -> stringBulider.append(kvMap.get(e)).append(";"));
        return stringBulider.deleteCharAt(stringBulider.length() - 1).toString();
    }

    private String trimBothEndsChars(String srcStr, String splitter) {
        String regex = "^" + splitter + "*|" + splitter + "*$";
        return srcStr.replaceAll(regex, "");
    }
}
